//
//  BlueToothManager.m
//  BlueToothDemo
//
//  Created by US bike on 2017/8/14.
//  Copyright © 2017年 US bike. All rights reserved.
//

#import "BlueToothManager.h"
#import "BabyBlueTooth.h"
#import <UIKit/UIKit.h>

#define SERVICE_UUID @"CCC1"
#define CHARACTERISTIC_UUID_READ @"DDD0" //读
#define CHARACTERISTIC_UUID_SUBSCRIPT @"DDD1" //订阅
#define CHARACTERISTIC_UUID_WRITE @"DDD2" //写
#define BLUETOOTH_NAME @"iPhone"//蓝牙名称


@implementation BlueToothResponse

@end



static BlueToothManager *shareObj;




static BlueToothManager *shareObj;


@interface BlueToothManager()
@property (nonatomic, strong) BabyBluetooth *baby;

//要发送的消息列表
@property (nonatomic, strong) NSMutableArray<NSData *> *sendDataArray;

@property (nonatomic, strong) CBPeripheral *selectedPeriphral;
@property (nonatomic, strong) CBCharacteristic *writeCharacteristic;

@property (nonatomic, strong) NSTimer *sendTimer;

@property (nonatomic, copy) BlueToothPeripheralBlock receiveMessageBlock;
@property (nonatomic, copy) BlueToothFailureBlock failureBlock;

@property (nonatomic, strong) NSMutableData *receiveMsgData;
@property (nonatomic, assign) NSInteger dataLength;
@end



@implementation BlueToothManager

+ (instancetype) sharedBlueToothManager {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareObj = [[super allocWithZone:NULL] init];
    });
    
    return shareObj;
}

+ (instancetype) allocWithZone:(struct _NSZone *)zone {
    return [[self class] sharedBlueToothManager];
}



#pragma mark - 公有方法
//设置要连接的蓝牙设备的标识 可以通过name
- (void) setupBeforeConnectWithName:(NSString *) nameStr {
    
    
    self.baby = [BabyBluetooth shareBabyBluetooth];
    
    //设置代理方法
    [self babyBlueToothDelegateWithName:nameStr];
    
    
    self.baby.scanForPeripherals().connectToPeripherals().discoverServices().discoverCharacteristics().begin();
    
    
}

//主动发送数据到蓝牙外设
- (void) sendMessageData:(NSData *) sendData {
    
    if (self.baby.centralManager.state == CBManagerStatePoweredOff) {
        [self requestUserBlueToothAuth];
    }
    
    if (!self.sendDataArray) {
        self.sendDataArray = [NSMutableArray array];
    }
    
    
    //添加到队列，等待发送
    if (sendData) {
        [self.sendDataArray addObject:sendData];
    }
    
    
    if (self.sendTimer) {
        [self.sendTimer invalidate];
        self.sendTimer = nil;
    }
    
    self.sendTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(senderNextData) userInfo:nil repeats:YES];
    [self.sendTimer fire];
}


//读取蓝牙设备返回的数据
- (void) setupReceiveMessageBlock:(BlueToothPeripheralBlock) block {
    self.receiveMessageBlock = block;
}

- (void) setupBlueToothFailureBlock:(BlueToothFailureBlock) block {
    self.failureBlock = block;
}

//取消所有连接 以及 停止扫描
- (void) cancellAll {
    
    if (self.baby.findConnectedPeripherals.count > 0) {
        [self.baby AutoReconnectCancel:self.baby.findConnectedPeripherals[0]];
    }
    [self.baby stop];
    [self.baby cancelScan];
    [self.baby cancelAllPeripheralsConnection];
}


#pragma mark - 私有方法
- (void) babyBlueToothDelegateWithName:(NSString *) nameStr {
    
    __weak typeof(self) weakSelf = self;
    
    
    [self.baby setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
        
        
        
        switch (central.state) {
            case CBManagerStatePoweredOn:
                //设置委托后直接可以使用，无需等待CBCentralManagerStatePoweredOn状态
                //weakSelf.baby.scanForPeripherals().connectToPeripherals().discoverServices().discoverCharacteristics().begin();
                break;
                
            case CBManagerStatePoweredOff:
                
                [weakSelf requestUserBlueToothAuth];
                
                break;
            default:
                break;
        }
    }];
    
    //设置扫描到设备的委托
    [self.baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"搜索到了设备:%@",peripheral.name);
        
        if ([peripheral.name isEqualToString:nameStr]) {
            //设置设备断线自动连接
            [weakSelf.baby AutoReconnect:peripheral];
            [weakSelf.baby cancelScan];
            
        }
    }];
    
    //连接Peripherals成功的委托
    [self.baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        
        NSLog(@"蓝牙设备连接成功, name = %@", peripheral.name);
        weakSelf.selectedPeriphral = peripheral;
    }];
    
    //连接Peripherals失败的委托
    [self.baby setBlockOnFailToConnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"蓝牙设备连接失败");
        if (weakSelf.failureBlock) {
            weakSelf.failureBlock();
        }
    }];
    
    //断开Peripherals的连接
    [self.baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"断开蓝牙设备,error = %@",error);
        weakSelf.selectedPeriphral = nil;
        weakSelf.writeCharacteristic = nil;
    }];
    
    
    //设置查找服务回调
    [self.baby setBlockOnDiscoverServices:^(CBPeripheral *peripheral, NSError *error) {
        NSLog(@"查找服务回调,error = %@",error);
    }];
    
    
    //设置查找到Characteristics的block
    [self.baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"查找特征回调,error = %@",error);
        
        for (CBCharacteristic *temp in service.characteristics) {
            
            if ([temp.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_SUBSCRIPT]) {
                [peripheral setNotifyValue:YES forCharacteristic:temp];
                
            } else if ([temp.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_WRITE]) {
                weakSelf.writeCharacteristic = temp;
                
                
            } else if ([temp.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_READ]) {
                
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [peripheral readValueForCharacteristic:temp];
                });
            }
        }
    }];
    
    
    //设置获取到最新Characteristics值的block
    [self.baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"读取到数据回调,error = %@",error);
        if ([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_READ]) {
            
            NSData *resultData = characteristic.value;
            NSString *resultStr = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
            
            NSLog(@"主动读取到的数据是:%@",resultStr);
            
            if (weakSelf.receiveMessageBlock) {
                BlueToothResponse *response = [BlueToothResponse new];
                response.data = characteristic.value;
                response.info = @"主动读取到数据";
                response.type = BlueToothResponseTypeReadSucced;
                weakSelf.receiveMessageBlock(YES, response);
            }
            
            
        } else if ([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_SUBSCRIPT]) {
            
            
            //处理接收消息
            [weakSelf receiveSubscriptMessageWithData:characteristic.value];
            
        }
    }];
    
    
    
    //写Characteristic成功后的block
    [self.baby setBlockOnDidWriteValueForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"写入数据回调,error = %@",error);
        
        
        if ([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_WRITE]) {
            NSData *resultData = characteristic.value;
            NSString *resultStr = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
            
            NSLog(@"发送出去的数据是:%@",resultStr);
            
        }
    }];
    
    
    //characteristic订阅状态改变的block
    [self.baby setBlockOnDidUpdateNotificationStateForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"订阅状态改变回调,error = %@",error);
        if ([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_UUID_SUBSCRIPT]) {
            if (characteristic.isNotifying) {
                NSLog(@"成功订阅");
            } else {
                NSLog(@"取消订阅");
            }
        }
    }];
    
    
    //设置蓝牙使用的参数参数
    //设置扫描时候，过滤已经发现的设备
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@NO,
                                                    CBCentralManagerOptionShowPowerAlertKey:@NO};
    //应用被挂起时，连接发生变化弹出提示框
    NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnDisconnectionKey: @YES};
    
    //服务列表
    NSArray *serviceArray = @[[CBUUID UUIDWithString:SERVICE_UUID]];
    
    NSArray *characteristicArray = @[[CBUUID UUIDWithString:CHARACTERISTIC_UUID_READ],[CBUUID UUIDWithString:CHARACTERISTIC_UUID_WRITE],[CBUUID UUIDWithString:CHARACTERISTIC_UUID_SUBSCRIPT]];
    
    [self.baby setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:connectOptions scanForPeripheralsWithServices:serviceArray discoverWithServices:serviceArray discoverWithCharacteristics:characteristicArray];
    
    
    
    //过滤器
    //设置查找设备的过滤器
    [self.baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"发现设备：name = %@", peripheralName);
        if ([peripheralName isEqualToString:nameStr]) {
            NSLog(@"找到指定的设备！！！！");
            return YES;
        }
        return NO;
    }];
    
    [self.baby setFilterOnConnectToPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        
        if ([peripheralName isEqualToString:nameStr]) {
            NSLog(@"开始连接指定的设备！！！！ name = %@", peripheralName);
            return YES;
        }
        return NO;
        
    }];
    
    
}


- (void) senderNextData {
    
    
    
    if (self.sendDataArray.count > 0) {
        
        
        if (self.selectedPeriphral.state == CBPeripheralStateConnected && self.writeCharacteristic) {
            
            NSData *sendData  = self.sendDataArray[0];
            //从队列中移除
            [self.sendDataArray removeObjectAtIndex:0];
            
            
            /*
            
            NSInteger dataLen = sendData.length;
            
            
            NSLog(@"数据内容是:%@, 数据总长度是:%ld\n",sendData,(long)dataLen);
            
            NSInteger count = ceilf(dataLen/20.0);
            NSLog(@"总共需要发送的次数是：%ld",(long)count);
            
            
            for (NSInteger i= 0; i < count; i++) {
                NSInteger currentLen = 20;
                if (dataLen - i*20 < 20) {
                    currentLen = dataLen - i*20;
                }
                NSLog(@"本次发送的数据长度是：%ld",(long)currentLen);
                NSData *subData = [sendData subdataWithRange:NSMakeRange(i*20, currentLen)];
                NSLog(@"本次发送的数据是:%@",subData);
                
                [self.selectedPeriphral writeValue:subData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
                
                usleep(200);
            }
             */
            
            //测试一次性发送
            [self.selectedPeriphral writeValue:sendData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
            NSLog(@"发送的数据是：%@",[[NSString alloc] initWithData:sendData encoding:NSUTF8StringEncoding]);
        }
        
    } else {
        NSLog(@"没有要发送的消息了");
        [self.sendTimer invalidate];
        self.sendTimer = nil;
    }
}




- (void) receiveSubscriptMessageWithData:(NSData *) data {
    
    //测试一次性接收
    
     NSLog(@"收到数据，数据是:%@", [[NSString alloc] initWithData:self.receiveMsgData encoding:NSUTF8StringEncoding]);
     //开始回调函数
     if (self.receiveMessageBlock) {
     BlueToothResponse *response = [BlueToothResponse new];
     response.type = BlueToothResponseTypeReadSubscriptSucced;
     response.info = @"收到数据";
     response.data = data;
     self.receiveMessageBlock(YES, response);
     }
     
    
    /*
    //拼接转发给后台
    NSLog(@"接收的一个数据段，开始拼接。数据段是：%@",data);
    if (data) {
        
        Byte *testByte = (Byte *)[data bytes];
        
        if (testByte[0] == 0xF8 && [data length] > 3) {
            
            NSInteger tempLength = (testByte[1] << 8) + testByte[2];
            
            if (tempLength > 15 & tempLength < 250) {//首个数据段
                self.dataLength = (testByte[1] << 8) + testByte[2];
                self.receiveMsgData = [NSMutableData dataWithData:data];
            } else {
                //不是首个段，直接拼接
                [self.receiveMsgData appendData:data];
            }
            
        } else {//拼接
            
            [self.receiveMsgData appendData:data];
        }
        
        //判断有没有接收到完整的数据包
        if (self.receiveMsgData.length == self.dataLength && testByte[data.length - 1] == 0x18) {//收到完整数据
            
            NSLog(@"收到完整的数据包，数据是:%@", self.receiveMsgData);
            //开始回调函数
            if (self.receiveMessageBlock) {
                BlueToothResponse *response = [BlueToothResponse new];
                response.type = BlueToothResponseTypeReadSubscriptSucced;
                response.info = @"收到完整的数据包。";
                response.data = self.receiveMsgData;
                self.receiveMessageBlock(YES, response);
            }
            
            self.receiveMsgData = nil;
            self.dataLength = 0;
        } else if (self.receiveMsgData.length > self.dataLength || self.receiveMsgData.length > 250) {//无效数据
            //开始回调函数
            if (self.receiveMessageBlock) {
                BlueToothResponse *response = [BlueToothResponse new];
                response.type = BlueToothResponseTypeReadSubscriptFailue;
                response.info = @"收到的数据有误。";
                response.error = [NSError new];
                self.receiveMessageBlock(NO, response);
            }
            
            self.receiveMsgData = nil;
            self.dataLength = 0;
        }
    }
     */
}

//向用户请求蓝牙权限
- (void) requestUserBlueToothAuth {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"打开蓝牙提醒" message:@"使用该车辆需要您打开蓝牙" preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        
        [self openBlueToothSetting];
        
    }]];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"取消用车" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        [self cancellAll];
        if (self.failureBlock) {
            self.failureBlock();
        }
    }]];
    
    //如果用户没有打开蓝牙， 提示用户打开，并且做相应动作
     UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
     UIViewController *topVC = appRootVC;
     while (topVC.presentedViewController) {
         topVC = topVC.presentedViewController;
     }
    
    [topVC presentViewController:alert animated:YES completion:^{
    }];
}

//打开蓝牙设置
- (void) openBlueToothSetting {
    
    NSString * urlString = @"App-Prefs:root=Bluetooth";
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
        
        if ([UIDevice currentDevice].systemVersion.floatValue > 10.0) {
            
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString] options:@{} completionHandler:^(BOOL success) {
                
            }];
            
        } else {
            
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
            
        }
    }
}

@end
